import 'package:flutter/cupertino.dart';
import '../pages/home_page.dart';
import '../pages/login_page.dart';
import '../pages/splash_page.dart';



// 全局导航键
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();



const Type _HOME_ = SplashScreen;
final _routes = RouterHelper.routeDefine({
  LoginPage: (_) => LoginPage(),
  HomePage: (_) => HomePage(),
  SplashScreen: (_) => SplashScreen(),
});

class RouterManager {
  RouterManager._();

  // 临时变量用于保存路由参数
  // -------------------------
  Object? _arguments;
  String? _routeName;
  BuildContext? _context;

  /// 路由定义
  static final routes = _routes;

  /// 单实例对象
  static final RouterManager _instance = RouterManager._();

  /// 对外部公开首页的路由名
  static final String INDEX = RouterHelper.typeName(_HOME_);

  /// 重置临时变量
  void _resetVariables() {
    _context = null;
    _arguments = null;
    _routeName = null;
  }

  /// 携带参数跳转
  // 添加参数验证
  Future<T?> to<T extends Object?>() {
    if (_context == null) throw StateError('Context not initialized');
    if (_routeName == null) throw StateError('Route name not set');
    try {
      return Navigator.pushNamed<T>(
        _context!,
        _routeName!,
        arguments: _arguments,
      );
    } finally {
      _resetVariables();
    }
  }

  // 添加更多导航方法
  static Future<T?> replace<T extends Object?, TO extends Object?>(
    BuildContext context,
    Type router, {
    TO? result,
    Object? arguments,
  }) {
    final name = _validateRoute(router);
    return Navigator.pushReplacementNamed(
      context,
      name,
      result: result,
      arguments: arguments,
    );
  }

  /// 不带任何参数的路由跳转
  static Future<T?> routeTo<T extends Object?>(
      BuildContext context, Type router) {
    final name = RouterHelper.typeName(router); // 将传入的 Type 转换成字符串
    assert(routes.containsKey(name), "Route \"$router\" is not registered.");
    return Navigator.pushNamed<T>(context, name);
  }

  static void popUntil(BuildContext context, Type anchorRoute) {
    final name = _validateRoute(anchorRoute);
    Navigator.popUntil(context, ModalRoute.withName(name));
  }

  static String _validateRoute(Type router) {
    final name = RouterHelper.typeName(router);
    if (!_routes.containsKey(name)) {
      throw FlutterError('Route "$router" is not registered');
    }
    return name;
  }

  /// 静态设置参数，这个方法主要是用于在路由跳转时调用
  /// 然后通过上面设置的临时变量进行保存，最后调用 to 时传递过去
  static RouterManager _withArguments(dynamic arguments) {
    _instance._arguments = arguments;
    return _instance;
  }

  /// 这里就是确定路由参数的核心
  /// 由于定义路由时是通过：(_) => Page() 这种方式；
  /// 所以这里可以利用这种规则，我们先对这个函数调用一次，这样的话可以获取到对应页面的实例对象；
  /// 因为页面在混入 RouterBridge 时就已经确定好了入参类型，所以我们这里我们直接返回
  /// 具体的页面实例对象，就可以调用 RouterBridge 混入类中的 arguments 方法，
  /// 而当我们调用 arguments 方法时，内部又是返回的 MyRouter 单例对象，所以就将外部设置的
  /// 参数又传回来了，然后保存到上面声明的临时变量中。
  static RT of<RT extends RouterBridge>(BuildContext context) {
    assert(RT != RouterBridge<dynamic>,
        "You must specify the route type, for example: of<Page>(context)");
    final name = RouterHelper.typeName(RT);
    assert(hasName(name), "Route \"$RT\" is not registered.");
    _instance._context = context; // 临时保存 context
    _instance._routeName = name; // 临时保存路由名
    var builder = _routes[name]!; // 取得 WidgetBuilder 对象
    // 这里调用一次就可以获得对应的页面实例对象
    // 既然获得了实例对象，上面的页面又混入了对应的 RouterBridge，在后续调用 arguments 方法时
    // 就能唯一的确定具体路由需要的参数类型
    return builder.call(context) as RT;
  }

  // 这个是在 MaterialApp 定义路由中需要使用的
  static CupertinoPageRoute onGenerateRoute<T>(RouteSettings settings) {
    final builder = _routes[settings.name] ?? _routes[INDEX]!;
    return CupertinoPageRoute<T>(builder: builder, settings: settings);
  }

  static bool hasName(String name) {
    return _routes.containsKey(name);
  }
}

// 修改RouterBridge混入类
mixin RouterBridge<T> {
  // 简化泛型声明
  RouterManager arguments(T args) => RouterManager._withArguments(args);

  T? argumentOf(BuildContext context) {
    final settings = ModalRoute.of(context)?.settings;
    if (settings == null) return null;

    try {
      return settings.arguments as T;
    } catch (e) {
      throw ArgumentError('''
        Expected ${T.toString()} but got ${settings.arguments.runtimeType}
        Route: ${settings.name}
        Error: $e
      ''');
    }
  }
}

class RouterHelper {
  RouterHelper._();

  /// 辅助方法，将类名转换成字符串（本义还是使用字符串，不过换了一种方式）
  static String typeName(Type type) => type.toString();

  // 新增支持路径参数
  static String pathName(Type type, [String? path]) => path ?? type.toString();

  // 增强路由定义方法
  static Map<String, WidgetBuilder> routeDefine(
    Map<Object, WidgetBuilder> defines, // 支持Type和String作为key
  ) {
    final target = <String, WidgetBuilder>{};
    defines.forEach((key, builder) {
      final name = key is Type ? typeName(key) : key.toString();
      target[name] = (context) {
        final route = builder(context);
        if (route is RouterBridge) {
          return route;
        }
        throw FlutterError('Route $name must mixin RouterBridge');
      };
    });
    return target;
  }
}

class RouteLogger extends NavigatorObserver {
  @override
  void didPush(Route route, Route? previousRoute) {
    debugPrint('Route pushed: ${route.settings.name}');
  }

  @override
  void didPop(Route route, Route? previousRoute) {
    debugPrint('Route popped: ${route.settings.name}');
  }
}
